#include "private_implementations/JsonArrayNode.h"
#include "private_implementations/JsonUtil.h"
#include <sstream>
#include <vector>
#include <iosfwd>

simframework::json::JsonArrayNode::JsonArrayNode(SimWString str)
{
	size_t s = str.find_first_of(L"[") + 1;
	size_t e = str.find_last_of(L"]");

	m_valueStr = str.substr(s, e-s);
	m_startIt = m_valueStr.begin();
	m_endIt = m_valueStr.end();
	m_valueCount = 0;
}

simframework::json::JsonAbstractNode*	simframework::json::JsonArrayNode::getValue(JSONType type, unsigned int id, int* status)
{
	JsonAbstractNode* data = NULL;

	switch (type)
	{
	case JSON_OBJECT:
		data = JSONUtil::getObjectElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	case JSON_ARRAY:
		data = JSONUtil::getArrayElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	case JSON_STRING:
		data = JSONUtil::getStringElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	case JSON_FLOAT:
		data = JSONUtil::getFloatElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	case JSON_INTEGER:
		data = JSONUtil::getIntElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	case JSON_BOOLEAN:
		data = JSONUtil::getBooleanElementById(id, m_valueCount, m_startIt, m_endIt, status);
		break;
	default:
		{
			if (status) *status = JSON_FAIL;
			data = JSONUtil::getDefault(type);
		}
		break;
	}
	m_valueCount++;
	return data;
}

simframework::json::JsonObjectNode* simframework::json::JsonArrayNode::getObjectValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return static_cast<JsonObjectNode*>(JSONUtil::getDefault(JSON_OBJECT));
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);
	if (*m_startIt != '{')
	{
		if (status) *status = JSON_FAIL;
		return static_cast<JsonObjectNode*>(JSONUtil::getDefault(JSON_OBJECT));
	}
	return static_cast<JsonObjectNode*>(getValue(JSON_OBJECT, id, status));
}

simframework::json::JsonArrayNode* simframework::json::JsonArrayNode::getArrayValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return static_cast<JsonArrayNode*>(JSONUtil::getDefault(JSON_ARRAY));
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);
	if (*m_startIt != '[')
	{
		if (status) *status = JSON_FAIL;
		return static_cast<JsonArrayNode*>(JSONUtil::getDefault(JSON_ARRAY));
	}
	return static_cast<JsonArrayNode*>(getValue(JSON_ARRAY, id, status));
}

SimWString	simframework::json::JsonArrayNode::getStringValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return L"";
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);
	if (*m_startIt != '"')
	{
		if (status) *status = JSON_FAIL;
		return L"";
	}

	int err;
	JSONString* data = static_cast<JSONString*>(getValue(JSON_STRING, id, &err));
	if (data)
	{
		if (err == JSON_SUCCESS)
		{
			if (status) *status = err;
			SimWString retVal = data->strValue;
			delete data;
			return retVal;
		}
		else if(err == JSON_NULL)
		{
			if (status) *status = err;
			return L"";
		}
	}
	if (status) *status = JSON_FAIL;
	return L"";
}

double simframework::json::JsonArrayNode::getFloatValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return -1;
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);

	int err;
	JSONFloat* data = static_cast<JSONFloat*>(getValue(JSON_FLOAT, id, &err));
	if (data)
	{
		if (err == JSON_SUCCESS)
		{
			if (status) *status = err;
			double retVal = data->fValue;
			delete data;
			return retVal;
		}
		else if(err == JSON_NULL)
		{
			if (status) *status = err;
			return -1;
		}
	}
	if (status) *status = JSON_FAIL;
	return -1;
}

int	simframework::json::JsonArrayNode::getIntValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return -1;		
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);

	int err;
	JSONInteger* data = static_cast<JSONInteger*>(getValue(JSON_INTEGER, id, &err));
	if (data)
	{
		if (err == JSON_SUCCESS)
		{
			if (status) *status = err;
			int retVal = data->iValue;
			delete data;
			return retVal;
		}
		else if(err == JSON_NULL)
		{
			if (status) *status = err;
			return -1;
		}
	}
	if (status) *status = JSON_FAIL;
	return -1;
}

bool simframework::json::JsonArrayNode::getBooleanValueForId(unsigned int id, int* status)
{
	if (m_valueCount > 0 && id < m_valueCount)
	{
		if (status) *status = JSON_FAIL;
		return false;
	}
	JSONUtil::cleanUp(m_startIt, m_endIt);
	JSONUtil::removeSpaces(m_startIt, m_endIt);

	int err;
	JSONBoolean* data = static_cast<JSONBoolean*>(getValue(JSON_BOOLEAN, id, &err));
	if (data)
	{
		if (err == JSON_SUCCESS)
		{
			if (status) *status = err;
			bool retVal = data->bValue;
			delete data;
			return retVal;
		}
		else if(err == JSON_NULL)
		{
			if (status) *status = err;
			return false;
		}
	}
	if (status) *status = JSON_FAIL;
	return false;
}
